package com.ccf.business.etl.xxljob.executor;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ccf.business.etl.xxljob.admin.XxlJobAdminApi;
import com.ccf.business.etl.model.Task;
import com.ccf.business.etl.service.ITaskService;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.ZoneId;
import java.util.Date;

/**
 * 流程执行器接收xxl-job-admin 分发的任务处理
 * @author zhaoj
 * @create 2021/12/3
 */
@Component
@Slf4j
public class FlowJobExecutor {

    @Autowired
    private ITaskService taskService;

    @Autowired
    private XxlJobAdminApi xxlJobAdminApi;

    /**
     * 解析固定任务为FlowTaskJob的任务
     */
    @XxlJob("flowTaskJob")
    public ReturnT<String> flowTaskJob() throws Exception {
        long jobId = XxlJobHelper.getJobId();
        String param = XxlJobHelper.getJobParam();
        log.info("接收調度中心参数...[{}]:" + param);

        //为空直接返回
        if(StrUtil.isEmpty(param)) {
            return ReturnT.SUCCESS;
        }

        //获取任务
        Task task = taskService.getById(param);
        //如果任务已经不存在，则删除调度任务
        if(ObjectUtil.isEmpty(task)){
            xxlJobAdminApi.removeJobInfo(Convert.toStr(jobId));
        }
        log.info(task.toString());

        //判断是否结束任务
        if(endTask(task)) {
            //更新为已完成
            task.setStatus(Task.STATUS_FINISH);
            taskService.updateById(task);

            //暂停任务
            xxlJobAdminApi.stopJobInfo(Convert.toStr(jobId));
            return ReturnT.SUCCESS;
        }

        //判断是否能运行任务
        if(!validateRunJob(task)) {
            return ReturnT.SUCCESS;
        }

        //生成任务实例并发送任务到消息队列
        taskService.running(task);

        // 获取参数
        return ReturnT.SUCCESS;
    }

    /**
     * 校验是否允许任务
     * @return
     */
    private boolean validateRunJob(Task task){
        //判断任务是否在执行时间范围里面如果不在
        Date startDate =  Date.from(task.getStartDate().atZone(ZoneId.systemDefault()).toInstant());
        Date endDate = Date.from(task.getEndDate().atZone(ZoneId.systemDefault()).toInstant());
        long currentDate = System.currentTimeMillis();
        if(ObjectUtil.isNotNull(endDate)) {
            //延迟10秒
            if(currentDate > DateUtil.beginOfDay(startDate).getTime() && currentDate < (DateUtil.endOfDay(endDate).getTime() + 10 * 1000)) {
                //运行失败，等待中，运行中都可以执行任务
                if(Task.STATUS_FAIL.equals(task.getStatus()) || Task.STATUS_WAITTING.equals(task.getStatus()) || Task.STATUS_RUNNING.equals(task.getStatus())) {
                    return true;
                }
            }
        } else {
            if(currentDate > DateUtil.beginOfDay(startDate).getTime()) {
                //运行失败，等待中，运行中都可以执行任务
                if(Task.STATUS_FAIL.equals(task.getStatus()) || Task.STATUS_WAITTING.equals(task.getStatus()) || Task.STATUS_RUNNING.equals(task.getStatus())) {
                    return true;
                }
            }
        }
        return false;
    }


    /**
     * 是否结束任务
     * @return
     */
    private boolean endTask(Task task){
        Date endDate = Date.from(task.getEndDate().atZone(ZoneId.systemDefault()).toInstant());
        long currentDate = System.currentTimeMillis();
        if(ObjectUtil.isNotNull(endDate)) {
            //延迟10秒
            if( currentDate > (DateUtil.endOfDay(endDate).getTime() + 10 * 1000)) {
                return true;
            }
        }
        return false;
    }
}
